package com.yunji.cabinet.device.impl;

import com.google.common.collect.Lists;
import com.yunji.cabinet.bo.CapacityCeilingBO;
import com.yunji.cabinet.bo.CapacityQuantityBO;
import com.yunji.cabinet.cache.CabinetCache;
import com.yunji.cabinet.context.calculate.CabinetCalculate;
import com.yunji.cabinet.device.*;
import com.yunji.cabinet.device.factory.DeviceStrategyFactory;
import com.yunji.cabinet.domain.ContainerCell;
import com.yunji.cabinet.domain.DeviceEventDO;
import com.yunji.cabinet.dto.device.DeviceCommandDTO;
import com.yunji.cabinet.dto.device.DeviceShoppingDTO;
import com.yunji.common.exception.device.DeviceErrorEnum;
import com.yunji.common.exception.device.DeviceException;
import com.yunji.common.model.cache.CabinetCacheDTO;
import com.yunji.common.model.cache.ContainerTypeCacheDTO;
import com.yunji.common.utils.ConvertDataUtil;
import com.yunji.common.utils.JsonUtil;
import com.yunji.coffee.entity.bo.CommonDeviceInfoBO;
import com.yunji.coffee.entity.dto.CoffeeDetailInfoDTO;
import com.yunji.coffee.entity.dto.CoffeeInfoDTO;
import com.yunji.order.dto.OrderOrdinalDTO;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component(DeviceStrategyFactory.COFFEE)
public class CoffeeDeviceCommandEngine extends DeviceCommandEngine {

    @Override
    public String getTypeCode() {
        return ContainerTypeEnum.COFFEE.getTypeCode();
    }

    @Override
    public Integer getRssi(String imei) {
        CoffeeInfoDTO newest = DeviceSpinService.getNewest(imei, getTypeCode());
        if (newest != null)
            return newest.getRssi();
        else
            throw new DeviceException(DeviceErrorEnum.CHECKED_202509, imei);
    }

    @Override
    public List<Integer> topInfraredTest(String imei) {
        ContainerTypeCacheDTO containerType = CabinetCache.getContainerType(getTypeCode());
        CoffeeInfoDTO newest = DeviceSpinService.getNewest(imei, containerType.getTypeCode());
        if (newest != null) {
            List<CoffeeDetailInfoDTO> infoList = newest.getInfoList();
            List<Integer> list = new ArrayList<>();
            for (CoffeeDetailInfoDTO infoDTO : infoList) {
                list.add(containerType.getTypeHeight().intValue() - infoDTO.getDistance());
            }
            return list;
        } else
            throw new DeviceException(DeviceErrorEnum.CHECKED_202506, imei);
    }

    @Override
    public CommonDeviceInfoBO getDeviceInfo(DeviceEventDO deviceEventDO) {
        return new CommonDeviceInfoBO(JsonUtil.readValue(deviceEventDO.getBeforeCmd(), CoffeeInfoDTO.class),
                JsonUtil.readValue(deviceEventDO.getAfterCmd(), CoffeeInfoDTO.class));
    }

    //FIXME tissueStatus需要去缓存去拿数据判断
    @Override
    public boolean tissueStatus(String imei, List<OrderOrdinalDTO> dtoList) {

        return true;
    }

    @Override
    public List<OrderOrdinalDTO> getProductNums(String imei) {
        Map<Integer, Long> cellMap = getCellMap(imei);
        CoffeeInfoDTO info = (CoffeeInfoDTO) DeviceInfoCache.getInfo(imei);
        List<CoffeeDetailInfoDTO> infoList = info.getInfoList();
        List<OrderOrdinalDTO> detailList = new ArrayList<>();
        for (CoffeeDetailInfoDTO infoDTO : infoList) {
            OrderOrdinalDTO dto = new OrderOrdinalDTO();

            Long productId = cellMap.get(infoDTO.getOrdinal());
            Integer distance = infoDTO.getDistance();
            Integer quantity = infoDTO.getTissueStatus() == 0 ? 0 :
                    CabinetCalculate.getQuantityByHeightDecimal(CapacityQuantityBO.builder().distance(distance).productId(productId).build()).intValue();
            dto.setOrdinal(infoDTO.getOrdinal());
            dto.setProductNums(quantity);
            detailList.add(dto);
        }
        return detailList;
    }

    @Override
    public Boolean shippingTest(String imei) {
        return DeviceCommandEngine.executeCommand(new DeviceCommandDTO(DeviceEventEnum.FACTORY_TEST.name(),
                DeviceCommandEnum.OPEN_SHIPPING.name(), imei, Lists.newArrayList(new DeviceShoppingDTO(1, 1),
                new DeviceShoppingDTO(2,1),new DeviceShoppingDTO(3,1),new DeviceShoppingDTO(4,1)
                ,new DeviceShoppingDTO(5,1),new DeviceShoppingDTO(6,1))));
    }

    @Override
    public boolean isLock(String imei) {
        CoffeeInfoDTO info = (CoffeeInfoDTO) DeviceInfoCache.getInfo(imei);
        return info != null && info.getLockStatus() == 1;
    }

    @Override
    public Integer getProductCeiling(String typeCode, Long productId) {
        return CabinetCalculate.getCapacityCeiling(new CapacityCeilingBO(typeCode, productId)).intValue();
    }

    private Map<Integer, Long> getCellMap(String imei) {
        CabinetCacheDTO cabinet = CabinetCache.getCabinet(imei);
        List<ContainerCell> cellList = CabinetCache.getCellList(cabinet.getContainerId());
        // 格子所代表的商品MAP
        return ConvertDataUtil.list2KeyValueMap(cellList, ContainerCell::getOrdinal, ContainerCell::getProductId);
    }
}
